home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
screen32.lha
/
screen-3.2b
/
socket.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-27
|
27KB
|
1,096 lines
/* Copyright (c) 1991
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Copyright (c) 1987 Oliver Laumann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING); if not, write to the
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Noteworthy contributors to screen's design and implementation:
* Wayne Davison (davison@borland.com)
* Patrick Wolfe (pat@kai.com, kailand!pat)
* Bart Schaefer (schaefer@cse.ogi.edu)
* Nathan Glasser (nathan@brokaw.lcs.mit.edu)
* Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
* Howard Chu (hyc@hanauma.jpl.nasa.gov)
* Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
* Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
* Marc Boucher (marc@CAM.ORG)
*
****************************************************************
*/
#ifndef lint
static char rcs_id[] = "$Id: socket.c,v 1.2 92/02/03 02:28:17 jnweiger Exp $ FAU";
#endif
#include "config.h"
#if defined(MIPS) || defined(GOULD_NP1) || defined(B43)
extern int errno;
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifndef sgi
# include <sys/file.h>
#endif
#ifndef NAMEDPIPE
#include <sys/socket.h>
#endif
#include <fcntl.h>
#ifndef NAMEDPIPE
#include <sys/un.h>
#endif
#include <signal.h>
#ifndef M_XENIX
#include <sys/time.h>
#endif /* M_XENIX */
#ifdef DIRENT
# include <sys/param.h>
# include <dirent.h>
#else
# include <sys/dir.h>
# define dirent direct
#endif
#include "screen.h"
#ifdef USEVARARGS
# if defined(__STDC__)
# include <stdarg.h>
# else
# include <varargs.h>
# endif
#endif
#include "extern.h"
#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
# define connect sconnect /* _SEQUENT_ has braindamaged connect */
#endif
extern char *RcFileName, *extra_incap, *extra_outcap;
extern WinList, Detached, ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
#ifdef BSDJOBS
extern int Suspended;
#endif
extern AttacherPid, dflag, rflag, lsflag, quietflag, wipeflag;
extern char HostName[];
extern struct mode OldMode, NewMode;
extern char display_tty[];
extern struct win *wtab[], *fore;
#ifdef NETHACK
extern nethackflag;
#endif
#ifdef PASSWORD
extern int CheckPassword;
extern char Password[];
#endif
#if defined(BSDJOBS) && !(defined(POSIX) || defined(SYSV))
extern DevTty;
#endif
extern char *getenv();
char SockPath[MAXPATH];
char *SockNamePtr, *SockName;
char *strdup(str)
#ifdef hpux
char *str;
#else
const char *str;
#endif
{
char *ret;
if ((ret = (char *) malloc(strlen(str) + 1)) == 0)
{
Msg_nomem;
return (0);
}
(void) strcpy(ret, str);
return (ret);
}
int RecoverSocket()
{
int s = 0, d;
(void) unlink(SockPath);
s = MakeServerSocket();
if (s != ServerSocket)
{
debug2("Oh, Serversocket was %d, now %d, let's dup!\n", ServerSocket, s);
d = dup2(s, ServerSocket);
close(s);
if (d != ServerSocket)
{
debug2("Hmm, dup2() failed, Serversocket was %d, now %d, bye\n",
ServerSocket, d);
return 0;
}
}
if (Detached)
(void) chmod(SockPath, /* S_IFSOCK | */ 0600); /* Flag detached-ness */
return 1;
}
/*
* Socket mode 700 means we are Attached. 600 is detached.
* We return how many sockets we found. If it was exactly one, we come
* back with a SockPath set to it and open it in a fd pointed to by fdp.
* If fdp == 0 we simply produce a list if all sockets.
*/
int FindSocket(how, fdp)
int how;
int *fdp;
{
register int s, lasts = 0, found = 0, deadcount = 0, wipecount = 0;
register int l;
register DIR *dirp;
register struct dirent *dp;
register char *Name;
struct stat st;
struct foundsock
{
char *name;
int mode;
} foundsock[100]; /* 100 is hopefully enough. */
int foundsockcount = 0;
/* User may or may not give us a (prefix) SockName. We want to search. */
debug("FindSocket:\n");
if (SockName)
{
debug1("We want to match '%s'\n", SockName);
l = strlen(SockName);
#ifdef NAME_MAX
if (l > NAME_MAX)
l = NAME_MAX;
#endif
}
#ifdef NFS_HACK
setreuid(eff_uid, real_uid);
#endif
debug1("FindSock searching... '%s'\n", SockPath);
/*
* this is a hack: SockName may point to Filename(Sockpath)...
*/
found = *SockNamePtr;
*SockNamePtr = '\0';
if ((dirp = opendir(SockPath)) == NULL)
{
Msg(0, "Cannot opendir %s", SockPath);
/* NOTREACHED */
}
*SockNamePtr = found;
found = 0;
while ((dp = readdir(dirp)) != NULL)
{
Name = dp->d_name;
/*
* there may be a file ".termcap" here.
* Ignore it just like "." and "..".
*/
if (Name[0] == '.')
continue;
debug2("Attach found: '%s', needed '%s'\n", Name, SockName);
if (SockName && l)
{
register char *n = Name;
/*
* The SockNames "hf", "ttyhf", "1", "12345.tty", "12345.ttyhf.medusa"
* all match the Name "12345.ttyhf.medusa".
*/
if ((*SockName <= '0' || *SockName > '9') && (*n > '0' && *n <= '9'))
{
while (*++n)
if (*n == '.')
{
n++;
break;
}
if (strncmp("tty", SockName, 3) && !strncmp("tty", n, 3))
n += 3;
}
if (strncmp(n, SockName, l))
{
debug3("strncmp('%s', '%s', %d)\n", n, SockName, l);
continue;
}
}
/*
* ATTENTION! MakeClientSocket adds SockName to SockPath!
* Anyway, we need it earlier.
*/
strcpy(SockNamePtr, Name);
if (stat(SockPath, &st))
continue;
if (st.st_uid != real_uid)
continue;
foundsock[foundsockcount].name = strdup(Name);
foundsock[foundsockcount].mode = s = st.st_mode & 0777;
debug2("FindSocket: %s has mode %04o...\n", Name, s);
if (s == 0700 || s == 0600)
{
/*
* We try to connect through the socket. If successfull,
* thats o.k. Otherwise we record that mode as -1.
* MakeClientSocket() must be careful not to block forever.
*/
if ((s = MakeClientSocket(0, Name)) == -1)
{
foundsock[foundsockcount].mode = -1;
deadcount++;
}
else
close(s);
}
if (++foundsockcount >= 100)
break;
}
closedir(dirp);
#ifdef NFS_HACK
setreuid(real_uid, eff_uid);
#endif
if (wipeflag)
{
for (s = 0; s < foundsockcount; s++)
{
if (foundsock[s].mode == -1)
{
strcpy(SockNamePtr, foundsock[s].name);
debug1("wiping '%d'\n", SockPath);
if (unlink(SockPath) == 0)
{
foundsock[s].mode = -2;
wipecount++;
}
}
}
}
for (s = 0; s < foundsockcount; s++)
if ((foundsock[s].mode) == (dflag ? 0700 : 0600))
{
found++;
lasts = s;
}
if (quietflag && (lsflag || (found != 1 && rflag != 2)))
eexit(10 + found);
debug2("attach: found=%d, foundsockcount=%d\n", found, foundsockcount);
if (found == 1 && lsflag == 0)
{
if ((lasts = MakeClientSocket(0, SockName = foundsock[lasts].name)) == -1)
found = 0;
}
else if (!quietflag && foundsockcount > 0)
{
switch (found)
{
case 0:
if (lsflag)
{
#ifdef NETHACK
if (nethackflag)
printf("Your inventory:\n");
else
#endif
printf((foundsockcount > 1) ?
"There are screens on:\n" : "There is a screen on:\n");
}
else
{
#ifdef NETHACK
if (nethackflag)
printf("Nothing fitting exists in the game:\n");
else
#endif
printf((foundsockcount > 1) ?
"There are screens on:\n" : "There is a screen on:\n");
}
break;
case 1:
#ifdef NETHACK
if (nethackflag)
printf((foundsockcount > 1) ?
"Prove thyself worthy or perish:\n" :
"You see here a good looking screen:\n");
else
#endif
printf((foundsockcount > 1) ?
"There are several screens on:\n" :
"There is a possible screen on:\n");
break;
default:
#ifdef NETHACK
if (nethackflag)
printf((foundsockcount > 1) ?
"You may whish for a screen, what do you want?\n" :
"You see here a screen:\n");
else
#endif
printf((foundsockcount > 1) ?
"There are several screens on:\n" : "There is a screen on:\n");
break;
}
for (s = 0; s < foundsockcount; s++)
{
switch (foundsock[s].mode)
{
case 0700:
printf("\t%s\t(Attached)\n", foundsock[s].name);
break;
case 0600:
printf("\t%s\t(Detached)\n", foundsock[s].name);
break;
case -1:
#if defined(__STDC__) || defined(_AIX)
printf("\t%s\t(Dead ??\?)\n", foundsock[s].name);
#else
printf("\t%s\t(Dead ???)\n", foundsock[s].name);
#endif
break;
case -2:
printf("\t%s\t(Removed)\n", foundsock[s].name);
break;
default:
printf("\t%s\t(Wrong mode)\n", foundsock[s].name);
break;
}
}
}
if (deadcount && !quietflag)
{
if (wipeflag)
{
#ifdef NETHACK
if (nethackflag)
printf("You hear%s distant explosion%s.\n",
(deadcount > 1) ? "" : " a", (deadcount > 1) ? "s" : "");
else
#endif
printf("%d Socket%s wiped out.\n", deadcount, (deadcount > 1)?"s":"");
}
else
{
#ifdef NETHACK
if (nethackflag)
printf("The dead screen%s touch%s you. Try 'screen -wipe'.\n",
(deadcount > 1) ? "s" : "", (deadcount > 1) ? "" : "es");
else
#endif
printf("Remove dead Sockets with 'screen -wipe'.\n");
}
}
for (s = 0; s < foundsockcount; s++)
Free(foundsock[s].name);
if (found == 1 && fdp)
*fdp = lasts;
if (fdp)
return found;
return foundsockcount - wipecount;
}
#ifdef NAMEDPIPE
int
MakeServerSocket()
{
register int s;
struct stat st;
strcpy(SockNamePtr, SockName);
#ifdef NAME_MAX
if (strlen(SockNamePtr) > NAME_MAX)
{
debug2("MakeClientSocket: '%s' truncated to %d chars\n",
SockNamePtr, NAME_MAX);
SockNamePtr[NAME_MAX] = '\0';
}
#endif
if ((s = open(SockPath, O_WRONLY | O_NDELAY)) >= 0)
{
debug("huii, my fifo already exists??\n");
if (quietflag)
{
Kill(AttacherPid, SIG_BYE);
eexit(11);
}
printf("There is already a screen running on %s.\n",
Filename(SockPath));
if (stat(SockPath, &st) == -1)
Msg(errno, "stat");
if (st.st_uid != real_uid)
Msg(0, "Unfortunatelly you are not its owner.");
if ((st.st_mode & 0700) == 0600)
Msg(0, "To resume it, use \"screen -r\"");
else
Msg(0, "It is not detached.");
/* NOTREACHED */
}
(void) unlink(SockPath);
if (UserContext() > 0)
{
#if defined(_POSIX_SOURCE) && defined(ISC)
if (mknod(SockPath, 0010700, 0))
#else
if (mknod(SockPath, S_IFIFO | S_IEXEC | S_IWRITE | S_IREAD, 0))
#endif
UserReturn(0);
UserReturn(1);
}
if (UserStatus() <= 0)
Msg(0, "mknod fifo %s failed", SockPath);
/*
* MUST be RDWR because otherwise we will get EOF's if
* nobody has opened the pipe for writing
*/
if ((s = secopen(SockPath, O_RDWR | O_NDELAY, 0)) < 0)
Msg(errno, "open fifo %s", SockPath);
return s;
}
int
MakeClientSocket(err, name)
int err;
char *name;
{
register int s = 0;
strcpy(SockNamePtr, name);
#ifdef NAME_MAX
if (strlen(SockNamePtr) > NAME_MAX)
{
debug2("MakeClientSocket: '%s' truncated to %d chars\n",
SockNamePtr, NAME_MAX);
SockNamePtr[NAME_MAX] = '\0';
}
#endif
if ((s = secopen(SockPath, O_WRONLY | O_NDELAY, 0)) >= 0)
{
(void) fcntl(s, F_SETFL, 0);
return s;
}
if (err)
{
Msg(errno, "open: %s (but continuing...)", SockPath);
debug1("MakeClientSocket() open %s failed\n", SockPath);
}
else
{
debug1("MakeClientSocket() open %s failed\n", SockPath);
}
return -1;
}
#else /* NAMEDPIPE */
int
MakeServerSocket()
{
register int s;
struct sockaddr_un a;
struct stat st;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
Msg(errno, "socket");
a.sun_family = AF_UNIX;
strcpy(SockNamePtr, SockName);
#ifdef NAME_MAX
if (strlen(SockNamePtr) > NAME_MAX)
{
debug2("MakeServerSocket: '%s' truncated to %d chars\n",
SockNamePtr, NAME_MAX);
SockNamePtr[NAME_MAX] = '\0';
}
#endif
strcpy(a.sun_path, SockPath);
if (connect(s, (struct sockaddr *) & a, strlen(SockPath) + 2) != -1)
{
debug("oooooh! socket already is alive!\n");
if (quietflag)
{
Kill(AttacherPid, SIG_BYE);
/*
* oh, well. nobody receives that return code. papa
* dies by signal.
*/
eexit(11);
}
printf("There is already a screen running on %s.\n",
Filename(SockPath));
if (stat(SockPath, &st) == -1)
Msg(errno, "stat");
if (st.st_uid != real_uid)
Msg(0, "Unfortunatelly you are not its owner.");
if ((st.st_mode & 0700) == 0600)
Msg(0, "To resume it, use \"screen -r\"");
else
Msg(0, "It is not detached.");
/* NOTREACHED */
}
(void) unlink(SockPath);
#ifndef NOREUID
setreuid(eff_uid, real_uid);
setregid(eff_gid, real_gid);
#endif
if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
Msg(errno, "bind");
(void) chmod(SockPath, /* S_IFSOCK | */ 0700);
#ifdef NOREUID
chown(SockPath, real_uid, real_gid);
#else
setreuid(real_uid, eff_uid);
setregid(real_gid, eff_gid);
#endif
if (listen(s, 5) == -1)
Msg(errno, "listen");
#ifdef F_SETOWN
fcntl(s, F_SETOWN, getpid());
debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0));
#endif /* F_SETOWN */
return s;
}
int
MakeClientSocket(err, name)
int err;
char *name;
{
register int s;
struct sockaddr_un a;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
Msg(errno, "socket");
a.sun_family = AF_UNIX;
strcpy(SockNamePtr, name);
#ifdef NAME_MAX
if (strlen(SockNamePtr) > NAME_MAX)
{
debug2("MakeClientSocket: '%s' truncated to %d chars\n",
SockNamePtr, NAME_MAX);
SockNamePtr[NAME_MAX] = '\0';
}
#endif
strcpy(a.sun_path, SockPath);
#ifndef NOREUID
setreuid(eff_uid, real_uid);
setregid(eff_gid, real_gid);
#else
if (access(SockPath, W_OK))
{
if (err)
Msg(errno, "%s", SockPath);
else
debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno);
close(s);
return -1;
}
#endif
if (connect(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
{
if (err)
Msg(errno, "%s: connect", SockPath);
else
debug("MakeClientSocket: connect failed.\n");
close(s);
s = -1;
}
#ifndef NOREUID
setreuid(real_uid, eff_uid);
setregid(real_gid, eff_gid);
#endif
return s;
}
#endif
void
SendCreateMsg(s, ac, av, aflag, flowflag, lflag, histheight, sterm)
int s, ac, aflag, flowflag, lflag, histheight;
char **av;
char *sterm;
{
struct msg m;
register char *p;
register int len, n;
debug1("SendCreateMsg() to '%s'\n", SockPath);
m.type = MSG_CREATE;
p = m.m.create.line;
for (n = 0; ac > 0 && n < MAXARGS - 1; ++av, --ac, ++n)
{
len = strlen(*av) + 1;
if (p + len >= m.m.create.line + MAXPATH - 1)
break;
strcpy(p, *av);
p += len;
}
if (!ac && *av && p + strlen(*av) + 1 < m.m.create.line + MAXPATH)
strcpy(p, *av);
else
*p = '\0';
m.m.create.nargs = n;
m.m.create.aflag = aflag;
m.m.create.flowflag = flowflag;
m.m.create.lflag = lflag;
m.m.create.hheight = histheight;
#ifdef SYSV
if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0)
#else
if (getwd(m.m.create.dir) == 0)
#endif
Msg(0, "%s", m.m.create.dir);
strncpy(m.m.create.screenterm, sterm, 19);
m.m.create.screenterm[19] = '\0';
debug1("SendCreateMsg writing '%s'\n", m.m.create.line);
if (write(s, (char *) &m, sizeof m) != sizeof m)
Msg(errno, "write");
}
void
#ifdef USEVARARGS
/*VARARGS1*/
# if defined(__STDC__)
SendErrorMsg(char *fmt, ...)
# else
SendErrorMsg(fmt, va_alist)
char *fmt;
va_dcl
#endif
{ /* } */
static va_list ap = 0;
#else
/*VARARGS1*/
SendErrorMsg(fmt, p1, p2, p3, p4, p5, p6)
char *fmt;
unsigned long p1, p2, p3, p4, p5, p6;
{
#endif
register int s;
struct msg m;
s = MakeClientSocket(1, SockName);
debug1("SendErrorMsg() to '%s'\n", SockPath);
m.type = MSG_ERROR;
#ifdef USEVARARGS
# if defined(__STDC__)
va_start(ap, fmt);
# else
va_start(ap);
# endif
(void) vsprintf(m.m.message, fmt, ap);
va_end(ap);
#else
sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6);
#endif
debug1("SendErrorMsg writing '%s'\n", m.m.message);
(void) write(s, (char *) &m, sizeof m);
close(s);
sleep(2);
}
#ifdef PASSWORD
static int CheckPasswd(pwd, pid, tty)
int pid;
char *pwd, *tty;
{
if (CheckPassword &&
strcmp(crypt(pwd, (strlen(Password) > 1) ? Password : "JW"),
Password))
{
if (*pwd)
{
#ifdef NETHACK
if (nethackflag)
Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", tty, pwd);
else
#endif
Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", tty, pwd);
}
debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid);
Kill(pid, SIG_PW_FAIL);
return 0;
}
debug1("CheckPass() from %d happy\n", pid);
Kill(pid, SIG_PW_OK);
return 1;
}
#endif /* PASSWORD */
static void ExecCreate(mp)
struct msg *mp;
{
char *args[MAXARGS];
register int n;
register char **pp = args, *p = mp->m.create.line;
for (n = mp->m.create.nargs; n > 0; --n)
{
*pp++ = p;
p += strlen(p) + 1;
}
*pp = 0;
if (!*p)
p = 0;
MakeWindow(p, args, mp->m.create.aflag, mp->m.create.flowflag,
0, mp->m.create.dir, mp->m.create.lflag,
mp->m.create.hheight, mp->m.create.screenterm);
}
static int
CheckPid(pid)
int pid;
{
if (pid < 2)
return(-1);
if (eff_uid == real_uid)
return kill(pid, 0);
if (UserContext() == 1)
{
UserReturn(kill(pid, 0));
}
return UserStatus();
}
void
ReceiveMsg(s)
int s;
{
int left, len, i;
static struct msg m;
char *p;
static char lbuf[20], cbuf[20]; /* static for later putenv()'s */
#ifdef NAMEDPIPE
/*
* we may be called if there are no pending messages, so we will have to
* block on first read.
*/
debug("Ha, there was someone knocking on my fifo??\n");
if (fcntl(s, F_SETFL, 0) == -1)
{
Msg(errno, "fcntl no O_NDELAY");
exit(1);
}
p = (char *) &m;
left = sizeof(m);
while (left > 0 && (len = read(s, p, left)) > 0)
{
/* if (p == (char *)&m)
* { if (fcntl(s, F_SETFL, O_NDELAY) == -1)
* { Msg(errno, "fcntl O_NDELAY !");
* return;
* }
* }
*/
p += len;
left -= len;
}
# ifdef DEBUG
if (len == 0)
debug("ReceiveMsg: Yucc! Got an EOF !!\n");
# endif
#else
register int ns;
struct sockaddr_un a;
len = sizeof(struct sockaddr_un);
debug("Ha, there was someone knocking on my socket??\n");
if ((ns = accept(s, (struct sockaddr *) & a, &len)) == -1)
{
Msg(errno, "accept");
return;
}
p = (char *) &m;
left = sizeof m;
while (left > 0 && (len = read(ns, p, left)) > 0)
{
p += len;
left -= len;
}
close(ns);
#endif /* NAMEDPIPE */
if (len == -1)
Msg(errno, "read");
if (left > 0)
return;
debug1("RecMsg: type %d !, ", m.type);
switch (m.type)
{
case MSG_WINCH:
/* Already processed in screen.c */
#ifdef notdef
CheckScreenSize(1); /* Change fore */
#endif
break;
case MSG_CREATE:
if (!Detached)
ExecCreate(&m);
break;
case MSG_CONT:
debug3("RecMsg: apid=%d,was %d, Detached=%d\n", m.m.attach.apid,
AttacherPid, Detached);
#ifdef SECURE_MSG_CONT
if (m.m.attach.apid != AttacherPid || !Detached)
/*
* now we realize, that there is something strange happening.
* First, there was some idiot who said "CONT" and thought
* "ATTACH". This is, when we have (AttacherPid == 0). Harmless.
* Let him in. Second, we are waiting for a certain AttacherPid,
* and not for "any" attacher. This is when (AttacherPid != 0).
* But Darwin's rule says "survival of the fittest", thus: Look
* weather "our" AttacherPid is still alive and well, and let the
* new one only in, if the old Attacher has been killed. jw.
*/
if (AttacherPid != 0 && kill(AttacherPid, 0) == 0)
break; /* Intruder Alert */
else
#endif /* SECURE_MSG_CONT */
AttacherPid = 0; /* we dont want to kill ourselves
* later. jw. */
/* FALLTHROUGH */
case MSG_ATTACH:
if (CheckPid(m.m.attach.apid))
{
debug1("Attach attempt with bad pid(%d)\n", m.m.attach.apid);
Msg(0, "Attach attempt with bad pid(%d) !", m.m.attach.apid);
break;
}
#ifdef PASSWORD
if (!CheckPasswd(m.m.attach.password, m.m.attach.apid, m.m.attach.tty))
{
debug3("RcvMsg:Checkpass(%s,%d,%s) failed\n",
m.m.attach.password, m.m.attach.apid, m.m.attach.tty);
break;
}
#endif /* PASSWORD */
if (!Detached)
{
debug("RecMsg: hey, why you disturb, we are not detached. hangup!\n");
Kill(m.m.attach.apid, SIG_BYE);
Msg(0, "Attach msg ignored: We are not detached.");
break;
}
#ifdef notdef
if ((i = secopen(m.m.attach.tty, O_RDWR | O_NDELAY, 0)) < 0)
#else
if ((i = secopen(m.m.attach.tty, O_RDWR, 0)) < 0)
#endif
{
debug1("ALERT: Cannot open %s!\n", m.m.attach.tty);
#ifdef NETHACK
if (nethackflag)
Msg(errno,
"You can't open (%s). Perhaps there's a Monster behind it.",
m.m.attach.tty);
else
#endif
Msg(errno, "Attach: Could not open %s", m.m.attach.tty);
Kill(m.m.attach.apid, SIG_BYE);
break;
}
errno = 0;
if (i)
{
debug("PANIC: open did not return fd 0!\n");
close(0);
dup(i);
close(i);
close(1);
close(2);
}
debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m.attach.tty);
#ifdef hpux_and_it_still_does_not_work
{
int pgrp, zero = 0;
if (ioctl(0, TIOCGPGRP, &pgrp) == -1)
debug1("tcgetpgrp: %d\n", errno); /* save old pgrp from tty */
if (ioctl(0, TIOCSPGRP, &zero) == -1)
debug1("tcsetpgrp: %d\n", errno); /* detach tty from proc grp */
#ifdef hpux
setpgrp();
#else
if (setpgrp(0, getpid()) == -1)
debug1("setpgrp: %d\n", errno); /* make me proc group leader */
#endif
close(0); /* reopen tty, now we should get it as our tty */
#ifdef notdef
(void)secopen(m.m.attach.tty, O_RDWR | O_NDELAY, 0); /* */
#else
(void)secopen(m.m.attach.tty, O_RDWR, 0); /* */
#endif
#ifdef hpux
setpgrp2(0, pgrp);
#else
setpgrp(0, pgrp);
#endif
ioctl(0, TIOCSPGRP, &pgrp);
}
#endif /* hpux_and_it_still_does_not_work */
(void) dup(0);
(void) dup(0);
GetTTY(0, &OldMode);
#if defined(BSDJOBS) && !(defined(POSIX) || defined(SYSV))
if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
{
debug1("DevTty not opened: %d.\n", errno);
Msg(errno, "/dev/tty");
}
#endif
signal(SIGHUP, SigHup);
#ifdef BSDJOBS
if (Suspended && m.type == MSG_ATTACH)
if (kill(AttacherPid, SIG_BYE) == 0)
kill(AttacherPid, SIGCONT);
#endif
AttacherPid = m.m.attach.apid;
strcpy(display_tty, m.m.attach.tty);
#ifdef UTMPOK
/*
* we set the Utmp slots again, if we were detached normally
* and if we were detached by ^Z.
*/
ReInitUtmp();
for (i = WinList; i != -1; i = wtab[i]->WinLink)
if (wtab[i]->slot != (slot_t) -1)
SetUtmp(wtab[i], i);
#endif
(void) chmod(SockPath, /* S_IFSOCK | */ 0700);
Detached = 0;
#ifdef BSDJOBS
Suspended = 0;
#endif
/*
* we like to have always the valid termcap, even if we are
* reattached from a different tty type. thus attacher had to
* tell us, what TERM we have. The attacher has correct env
* setting. we (the backend may be wrong).
*/
if (*m.m.attach.envterm)
{
#if defined(pyr) || defined(xelos) || defined(sequent)
/*
* Kludge for systems with braindamaged termcap routines,
* which evaluate $TERMCAP, regardless weather it describes
* the correct terminal type or not.
*/
if (strcmp(getenv("TERM"), m.m.attach.envterm + 5))
{
debug("a different terminal, so unsetenv(TERMCAP)");
unsetenv("TERMCAP");
}
#endif
putenv(m.m.attach.envterm);
}
sprintf(lbuf, "LINES=%d", m.m.attach.lines);
if (m.m.attach.lines > 0 || getenv("LINES"))
putenv(lbuf);
sprintf(cbuf, "COLUMNS=%d", m.m.attach.columns);
if (m.m.attach.columns > 0 || getenv("COLUMNS"))
putenv(cbuf);
/*
* We reboot our Terminal Emulator. Forget all we knew about
* the old terminal, reread the termcap entries in .screenrc
* (and nothing more from .screenrc is read. Mainly because
* I did not check, weather a full reinit is save. jw)
* and /etc/screenrc, and initialise anew.
*/
if (extra_outcap)
Free(extra_outcap);
if (extra_incap)
Free(extra_incap);
#ifdef ETCSCREENRC
if ((p = getenv("SYSSCREENRC")) == NULL)
StartRc(ETCSCREENRC);
else
StartRc(p);
#endif
StartRc(RcFileName);
InitTermcap();
InitTerm(m.m.attach.adaptflag);
SetMode(&OldMode, &NewMode);
SetTTY(0, &NewMode);
fore->active = 1;
Activate(0);
debug("activated...\n");
break;
case MSG_ERROR:
Msg(0, "%s", m.m.message);
break;
case MSG_HANGUP:
#ifdef REMOTE_DETACH
case MSG_DETACH:
# ifdef POW_DETACH
case MSG_POW_DETACH:
# endif /* POW_DETACH */
#endif
#ifdef REMOTE_DETACH
# ifdef POW_DETACH
if (m.type == MSG_POW_DETACH)
Detach(D_REMOTE_POWER);
else
# endif /* POW_DETACH */
if (m.type == MSG_DETACH)
Detach(D_REMOTE);
else
#endif
SigHup(SIGARG);
break;
default:
Msg(0, "Invalid message (type %d).", m.type);
}
}
#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
#undef connect
sconnect(s, sapp, len)
int s, len;
struct sockaddr *sapp;
{
register struct sockaddr_un *sap;
struct stat st;
int x;
sap = (struct sockaddr_un *)sapp;
if (stat(sap->sun_path,&st))
return -1;
chmod(sap->sun_path, 0);
x = connect(s, (struct sockaddr *) sap, len);
chmod(sap->sun_path, st.st_mode);
return x;
}
#endif